package server

// conn管理参考了 https://github.com/HDT3213/godis/tree/master/tcp
import (
	"context"
	"io"
	"log"
	"net"
	"os"
	"os/signal"
	"sync"
	"syscall"
)

var sigs = make(chan os.Signal)
var wg sync.WaitGroup
var connMap = sync.Map{}

func regSignal() {
	signal.Notify(sigs, syscall.SIGINT)
}

func RunTcpServer(addr string, proto ProtoHandler, debug bool) error {
	regSignal()
	if !debug {
		log.SetOutput(io.Discard)
	}
	log.Println("RunTcpServer...", "addr :", addr)
	ctx := context.Background()
	shutdown := make(chan struct{})
	go func() {
		<-sigs
		log.Println("sigs")
		shutdown <- struct{}{}
	}()

	listener, err := net.Listen("tcp", addr)
	if err != nil {
		return err
	}
	go func() {
		<-shutdown
		listener.Close()

		connMap.Range(func(key interface{}, val interface{}) bool {
			conn := key.(net.Conn)
			conn.Close()
			return true
		})
	}()
	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Println("accept error : ", err.Error())
			break
		}
		connMap.Store(conn, struct{}{})
		wg.Add(1)
		go func() {
			defer wg.Done()
			proto.Action(ctx, conn)
			log.Println("proto end...")
		}()
	}
	wg.Wait()

	return nil

}
